package cn.com.headfree.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;

import cn.com.headfree.base.common.SpringUtil;

public class FTPPoolUtils {

	private static final Logger logger = Logger.getLogger(FTPPoolUtils.class);

	/**
	 * FTP的连接池
	 */
	public static FTPClientPool ftpClientPool;
	/**
	 * FTPClient对象
	 */
	public static FTPClient ftpClient;

	private FTPProperties ftpProperties;
	private FTPClientFactory factory;

	private static FTPPoolUtils util;

	private FTPPoolUtils() {

	}

	public static FTPPoolUtils getInstance() {
		if (util == null) {
			util = new FTPPoolUtils();
			util.init();
		}
		return util;
	}

	public FTPClientFactory getFactory() {
		return this.factory;
	}

	/**
	 * 初始化设置
	 *
	 * @return
	 */
	@PostConstruct
	private boolean init() {
		ftpProperties = (FTPProperties) SpringUtil.getBean("fTPProperties");
		factory = FTPClientFactory.getInstance(ftpProperties);
		try {
			ftpClientPool = FTPClientPool.getInstance(factory);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 获取连接对象
	 *
	 * @return
	 * @throws Exception
	 */
	public FTPClient getFTPClient() throws Exception {
		// 初始化的时候从队列中取出一个连接
		if (ftpClient == null || ftpClient != null && !ftpClient.isConnected()) {
			synchronized (ftpClientPool) {
				ftpClient = ftpClientPool.borrowObject();
			}
		} else {
			ftpClient.enterLocalPassiveMode();
		}
		return ftpClient;
	}

	/**
	 * 当前命令执行完成命令完成
	 *
	 * @throws IOException
	 */
	public void complete() throws IOException {
		ftpClient.completePendingCommand();
	}

	/**
	 * 当前线程任务处理完成，加入到队列的最后
	 *
	 * @return
	 */
	public void disconnect() throws Exception {
		ftpClientPool.addObject(ftpClient);
	}

	/**
	 * Description: 向FTP服务器上传文件
	 *
	 * @param remoteFile 上传到FTP服务器上的文件名
	 * @param input      本地文件流
	 * @return 成功返回true，否则返回false @Version1.0
	 */
	public boolean uploadFile(String remoteFile, InputStream input) throws Exception {
		ftpClient.enterLocalPassiveMode();
		return ftpClient.storeFile(remoteFile, input);
	}

	public void changeFileDir(String ftpDir) throws IOException {
		String workingDirectory = ftpClient.printWorkingDirectory();
		logger.info("oldDirectory:" + workingDirectory);
		if (workingDirectory != null) {
			// 切换目录
			boolean b = ftpClient.changeWorkingDirectory(ftpDir);
			if (!b) {
				ftpClient.makeDirectory(ftpDir);
				ftpClient.changeWorkingDirectory(ftpDir);
			}
			workingDirectory = ftpClient.printWorkingDirectory();
			logger.info("newDirectory:" + workingDirectory);
		} else {
			throw new IOException("用戶登录未成功！");
		}
	}

	/**
	 * Description: 向FTP服务器上传文件
	 *
	 * @param remoteFile ftp上文件的名称，含路径
	 * @param localFile  本地文件的名称，含路径
	 * @return
	 */
	public boolean uploadFile(String remoteFile, String localFile) throws Exception {
		boolean resultFlag = false;
		FileInputStream inputStream = null;
		try {
			inputStream = new FileInputStream(new File(localFile));
			resultFlag = uploadFile(remoteFile, inputStream);
		} finally {
			if (inputStream != null) {
				inputStream.close();
			}
		}
		return resultFlag;
	}

	/**
	 * 获取ftp目录下的所有文件
	 *
	 * @param dir
	 * @return
	 */
	public FTPFile[] getFiles(String dir) throws Exception {
		FTPFile[] files = new FTPFile[0];
		try {
			files = ftpClient.listFiles(dir);
		} catch (Throwable thr) {
			thr.printStackTrace();
		}
		return files;
	}

	/**
	 * 获取ftp目录下的所有文件的名称
	 *
	 * @param dir 目录位置
	 * @return
	 * @throws Exception
	 */
	public List<String> getFileNames(String dir) throws Exception {
		List<String> filenames = new ArrayList<>();
		logger.info("ftp线程的连接状态：" + ftpClient.isConnected());
		// 设置ftp客户端线程为被动模式
		ftpClient.enterLocalPassiveMode();
		String[] ftpFileNames = ftpClient.listNames(dir);
		if (ftpFileNames != null) {
			for (String filename : ftpFileNames) {
				String[] split = filename.split("/");
				filenames.add(split[1]);
			}
		}
		return filenames;
	}

}
